package wpRelations;

import java.util.ArrayList;
import java.util.HashMap;

import processing.core.PApplet;
import processing.core.PFont;

public class WP_002 extends PApplet{
	
	wArticle wa;
	wCategory wc;
	wHub wh;
	
	Node[] nodes = new Node[100];
	HashMap nodeTable = new HashMap();
	public int nodeCount;
	int edgeCount;
	Edge[] edges = new Edge[500];

	static final int nodeColor   = 0xF0C070;
	static final int selectColor = 0xFF3030;
	static final int fixedColor  = 0xFF8080;
	static final int edgeColor   = 0x000000;
	public ArrayList<wNode> wNodes;

	PFont font;
	//String person_zero = "Albert_Einstein";
	String person_zero = "Coby_Miller";
	int personCount = 0;
	int nonPersonCount =0;
	int catCount =0;
	
	public void setup() {
     	  size(screen.width-200, screen.height-200,P3D);  
		  loadData();
		  //println(edgeCount);
		  font = createFont("SansSerif", 28);
		  textFont(font);  
		  smooth();
		  initWGraph();
		  textMode(MODEL);
//		System.out.println(wa.checkPerson());
//		wc = new wCategory(this, "Category:Pixar");
//		wc.init();
//		wc.printConnections();
	}
	
	public void draw() {
		  if (record) {
		    beginRecord(PDF, "output.pdf");
		  }
		  translate(width/2,height/2);
		  rotateY(map(mouseX,0,width,0,TWO_PI)-PI);
		  rotateX(map(mouseY,0,height,0,TWO_PI)-PI);
	
		  background(255);
		  //displayBensGraph();
		  displayWGraph();
		  if (record) {
		    endRecord();
		    record = false;
		  }
		}
	
	
	/**
	 * @param args
	 */
	public static void main(String _args[]) {
		PApplet.main(new String[] { wpRelations.WP_002.class.getName() });
	}
	// Code from Visualizing Data, First Edition, Copyright 2008 Ben Fry.
	// Based on the GraphLayout example by Sun Microsystems.


	void loadData() {

		wa = new wArticle(this, person_zero);
		wh = new wHub(this, wa);
		wh.init();
		wNodes = new ArrayList<wNode>();
		//wh.printContents();
		wNodes.add(new wNode(this, wa.title, wNodes, wNode.PERSON_ZERO));
		for (int i = 0; i < wh.links.size(); i++) {
		//	for (int i = 0; i < 2; i++) {
	//      addEdge(wh.core.toString(), wh.links.get(i).toString());
	      boolean isAPerson = wh.links.get(i).checkPerson();
	      if (isAPerson) {
	    	  wNodes.add(new wNode(this, wh.links.get(i).title, wNodes, wNode.PERSON, personCount));
	    	  personCount++;
	    	  System.out.println("person count: " + personCount);
	      } else {
	    	  wNodes.add(new wNode(this, wh.links.get(i).title, wNodes, wNode.NON_PERSON, nonPersonCount));
	    	  nonPersonCount++;
	    	  System.out.println("non-person count: " + nonPersonCount);
	      }
		}
		
		for (int i = 0; i < wh.backLinks.size(); i++) {
		//	for (int i = 0; i < 2; i++) {
		//	addEdge(wh.core.toString(), wh.backLinks.get(i).toString());
		      boolean isAPerson = wh.backLinks.get(i).checkPerson();
		      if (isAPerson) {
		    	  wNodes.add(new wNode(this, wh.backLinks.get(i).title, wNodes, wNode.PERSON,personCount));
		    	  personCount++;
		      } else {
		    	  wNodes.add(new wNode(this, wh.backLinks.get(i).title, wNodes, wNode.NON_PERSON,nonPersonCount));
		    	  nonPersonCount++;
		      }

		}
//		for (int i = 0; i < wh.superCategories.size(); i++) {
//		      addEdge(wh.core.toString(), wh.superCategories.get(i).toString());
//	    	  wNodes.add(new wNode(this, wh.superCategories.get(i).title, wNodes, wNode.CATEGORY,catCount));
//		      catCount++;
//		}
//			
//		for (int i = 0; i < wh.superCategories.size(); i++) {
//			int subCatSize = wh.superCategories.get(i).getSubCats().size();
//			for (int j = 0; j < subCatSize; j++) {
//				addEdge( wh.superCategories.get(i).toString(),wh.superCategories.get(i).getSubCats().get(j).toString());
//		    	  wNodes.add(new wNode(this, wh.superCategories.get(i).getSubCats().get(j).title, wNodes, wNode.CATEGORY,catCount));
//			      catCount++;
//			}
//		}
//		for (int i = 0; i < wh.superCategories.size(); i++) {
//			int subCatSize = wh.superCategories.get(i).getSubPages().size();
//			for (int j = 0; j < subCatSize; j++) {
//				addEdge( wh.superCategories.get(i).toString(),wh.superCategories.get(i).getSubPages().get(j).toString());
//				addEdge( wh.core.toString(),wh.superCategories.get(i).getSubPages().get(j).toString());
//			      boolean isAPerson = wh.superCategories.get(i).getSubPages().get(j).checkPerson();
//			      if (isAPerson) {
//			    	  wNodes.add(new wNode(this, wh.superCategories.get(i).getSubPages().get(j).title, wNodes, wNode.PERSON,personCount));
//			    	  personCount++;
//			      } else {
//			    	  wNodes.add(new wNode(this, wh.superCategories.get(i).getSubPages().get(j).title, wNodes, wNode.NON_PERSON,nonPersonCount));
//			    	  nonPersonCount++;
//			      }
//
//			}
//		}
		
	}


	void addEdge(String fromLabel, String toLabel) {
	  // Filter out unnecessary words
	 // if (ignoreWord(fromLabel) || ignoreWord(toLabel)) return;

	  Node from = findNode(fromLabel);
	  Node to = findNode(toLabel);
	  from.increment();
	  to.increment();
	  
	  for (int i = 0; i < edgeCount; i++) {
	    if (edges[i].from == from && edges[i].to == to) {
	      edges[i].increment();
	      return;
	    }
	  } 
	  
	  Edge e = new Edge( from, to);
	  e.increment();
	  if (edgeCount == edges.length) {
	    edges = (Edge[]) expand(edges);
	  }
	  edges[edgeCount++] = e;
	}


//	String[] ignore = { "a", "of", "the", "i", "it", "you", "and", "to" };
//
//	boolean ignoreWord(String what) {
//	  for (int i = 0; i < ignore.length; i++) {
//	    if (what.equals(ignore[i])) {
//	      return true;
//	    }
//	  }
//	  return false;
//	}


	Node findNode(String label) {
	  label = label.toLowerCase();
	  Node n = (Node) nodeTable.get(label);
	  if (n == null) {
	    return addNode(label);
	  }
	  return n;
	}


	Node addNode(String label) {
	  Node n = new Node(label);  
	  if (nodeCount == nodes.length) {
	    nodes = (Node[]) expand(nodes);
	  }
	  nodeTable.put(label, n);
	  nodes[nodeCount++] = n;  
	  return n;
	}





	boolean record;
	
	void displayBensGraph () {
	for (int i = 0 ; i < edgeCount ; i++) {
		    edges[i].relax();
		  }
		  for (int i = 0; i < nodeCount; i++) {
		    nodes[i].relax();
		  }
		  for (int i = 0; i < nodeCount; i++) {
		    nodes[i].update();
		  }
		  for (int i = 0 ; i < edgeCount ; i++) {
		    edges[i].draw();
		  }
		  for (int i = 0 ; i < nodeCount ; i++) {
		    nodes[i].draw();
		  }
	}
	
	void initWGraph() {
		for (int i = 0; i< wNodes.size(); i++) {
			wNodes.get(i).initPos();
		}
	}
	
	void displayWGraph() {
		for (int i = 0; i< wNodes.size(); i++) {
			wNodes.get(i).display();
		}
	}
	
	public void keyPressed() {
	  if (key == 'r') {
	    record = true;
	  }
	}


	Node selection; 


	public void mousePressed() {
	  // Ignore anything greater than this distance
	  float closest = 20;
	  for (int i = 0; i < nodeCount; i++) {
	    Node n = nodes[i];
	    float d = dist(mouseX, mouseY, n.x, n.y);
	    if (d < closest) {
	      selection = n;
	      closest = d;
	    }
	  }
	  if (selection != null) {
	    if (mouseButton == LEFT) {
	      selection.fixed = true;
	    } else if (mouseButton == RIGHT) {
	      selection.fixed = false;
	    }
	  }
	}


	public void mouseDragged() {
	  if (selection != null) {
	    selection.x = mouseX;
	    selection.y = mouseY;
	  }
	}


	public void mouseReleased() {
	  selection = null;
	}
	// Code from Visualizing Data, First Edition, Copyright 2008 Ben Fry.
	// Based on the GraphLayout example by Sun Microsystems.


	public class Edge {
	  Node from;
	  Node to;
	  float len;
	  int count;


	  Edge(Node from, Node to) {
	    this.from = from;
	    this.to = to;
	    this.len = 250;
	  }
	  
	  
	  void increment() {
	    count++;
	  }
	  
	  
	  void relax() {
	    float vx = to.x - from.x;
	    float vy = to.y - from.y;
	    float d = mag(vx, vy);
	    if (d > 0) {
	      float f = (len - d) / (d * 3);
	      float dx = f * vx;
	      float dy = f * vy;
	      to.dx += dx;
	      to.dy += dy;
	      from.dx -= dx;
	      from.dy -= dy;
	    }
	  }


	  void draw() {
		  if (count >= 2) {

	    stroke(edgeColor);
	    strokeWeight(0.35f);
	    line(from.x, from.y, to.x, to.y);
		  }
	  }
	}
	  
	
	// Code from Visualizing Data, First Edition, Copyright 2008 Ben Fry.
	// Based on the GraphLayout example by Sun Microsystems.


	public class Node {
	  float x, y;
	  float dx, dy;
	  boolean fixed;
	  String label;
	  int count;


	  Node(String label) {
	    this.label = label;
	    x = random(width);
	    y = random(height);
	  }
	  
	  
	  void increment() {
	    count++;
	  }
	  
	  
	  void relax() {
	    float ddx = 0;
	    float ddy = 0;

	    for (int j = 0; j < nodeCount; j++) {
	      Node n = nodes[j];
	      if (n != this) {
	        float vx = x - n.x;
	        float vy = y - n.y;
	        float lensq = vx * vx + vy * vy;
	        if (lensq == 0) {
	          ddx += random(1);
	          ddy += random(1);
	        } else if (lensq < 100*100) {
	          ddx += vx / lensq;
	          ddy += vy / lensq;
	        }
	      }
	    }
	    float dlen = mag(ddx, ddy) / 2;
	    if (dlen > 0) {
	      dx += ddx / dlen;
	      dy += ddy / dlen;
	    }
	  }


	  void update() {
	    if (!fixed) {      
	      x += constrain(dx, -5, 5);
	      y += constrain(dy, -5, 5);
	      
	      x = constrain(x, 0, width);
	      y = constrain(y, 0, height);
	    }
	    dx /= 2;
	    dy /= 2;
	  }


	  void draw() {
		  if (count >= 2) {
		  fill(color(nodeColor));
	    stroke(0);
	    strokeWeight(0.5f);
	    
	    ellipse(x, y, count*10, count*10);
	    float w = textWidth(label);
	    
	      fill(0);
	      textAlign(CENTER, CENTER);
	      fill(0,63);
	      text(label, x, y);
	    }
	  }
	}

	
}
